home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 2
/
AACD 2.iso
/
AACD
/
Magazine
/
GraphicsCards
/
StormMesa
/
src
/
MGL
/
mglmesa.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-02-04
|
45KB
|
1,224 lines
/****************************************************************************
*
* Mesa bindings for SciTech MGL
*
* Language: ANSI C
* Environment: Any
*
* Description: Main Mesa 3D library interface between the MGL and
* Mesa. For maximum peformance we call the MGL's internal
* rendering functions directly so we can bypass all the
* clipping and regular MGL API stuff as all that is already
* handled by Mesa before the calls get here.
*
* Note also that all rendering is inherently single threaded
* so we optimize for this case by using a global current
* context structure.
*
* This module contains generic interface routines.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
****************************************************************************/
#include "mgl/mmesap.h"
#pragma hdrstop
#include "GL/mglmesa.h"
#include <string.h>
#include <stdlib.h>
/*--------------------------- Global Variables ----------------------------*/
#ifdef __WINDOWS__
MGLCallbacks _MGL_callbacks; /* MGL callback functions */
#endif
gmode_t _MGL_mi; /* MGL mode information */
pixel_format_t _MGL_pf; /* MGL mode pixel format */
vecs _MGL_vecs; /* MGL Rendering vectors */
MGLRC _MM_rc; /* Current rendering context */
MGLRC *_MM_rcPtr = NULL; /* Pointer to current context */
/*------------------------- Implementation --------------------------------*/
#pragma warn -par
/**********************************************************************/
/***** Miscellaneous device driver funcs *****/
/**********************************************************************/
static void begin(GLcontext *ctx,GLenum mode)
/****************************************************************************
*
* Function: begin
*
* Description: Called when glBegin is called. We use this oportunity to
* enable direct framebuffer access for our rendering functions.
*
****************************************************************************/
{
// TODO: Call begin directAccess depending on the currently selected mode
// and also the current rendering attributes (to determine if we need
// to directly access the buffer. We need this to support VBE/AF.
//
// We should optimize this to have this code in here run fast, and
// put the complicated code into the setup_DD_funcs to avoid the
// overheads of checking in here.
_MGL_vecs.beginDirectAccess();
}
static void end(GLcontext *ctx)
/****************************************************************************
*
* Function: end
*
* Description: Called when glEnd is called. We use this oportunity to
* disable direct framebuffer access for our rendering
* functions.
*
****************************************************************************/
{
_MGL_vecs.endDirectAccess();
}
static void finish(GLcontext *ctx)
/****************************************************************************
*
* Function: finish
*
* Description: Called when glFinish is called. We simply do nothing here.
*
****************************************************************************/
{
}
static void flush(GLcontext *ctx)
/****************************************************************************
*
* Function: flush
*
* Description: Called when glFlush is called. We simply do nothing here
*
****************************************************************************/
{
}
static void clear_index(GLcontext *ctx, GLuint index)
/****************************************************************************
*
* Function: clear_index
* Parameters: index - New color index for buffer clears
*
* Description: Sets the current buffer clear color for color index buffers.
*
****************************************************************************/
{
RC.clearColor = index;
}
static void clear_color(GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a)
/****************************************************************************
*
* Function: clear_color
* Parameters: r,g,b,a - New RGBA color values for buffer clears
*
* Description: Set the current buffer clear color for TrueColor buffers.
* Note that Mesa passes us color values pre-scaled to the
* proper number of color bits:
*
* [0,ctx->Visual->RedScale]
* [0,ctx->Visual->GreenScale]
* [0,ctx->Visual->BlueScale]
* [0,ctx->Visual->AlphaScale]
*
****************************************************************************/
{
RC.clearColor = MGL_packColorFast(&PF,r,g,b);
}
static GLbitfield clear(GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x,
GLint y, GLint width, GLint height)
/****************************************************************************
*
* Function: clear
* Parameters: all - True to clear entire buffer
* x,y,width,height - Rectangle to clear
*
* Description: Clears the buffer in the current clear color
*
****************************************************************************/
{
if (mask & GL_COLOR_BUFFER_BIT) {
VECS.setColor(RC.clearColor);
if (all)
VECS.solid.fillRect(0,0,MI.xRes+1,MI.yRes+1);
else
VECS.solid.fillRect(x,y,x+width,y+height);
}
return mask & (~GL_COLOR_BUFFER_BIT);
}
static void set_index(GLcontext *ctx, GLuint index)
/****************************************************************************
*
* Function: clear_index
* Parameters: index - New color index
*
* Description: Sets the current solid color for color index buffers.
*
****************************************************************************/
{
RC.color = index;
}
static void set_color(GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a)
/****************************************************************************
*
* Function: set_color
* Parameters: r,g,b,a - New RGBA color value
*
* Description: Set the current solid color for TrueColor buffers.
* Note that Mesa passes us color values pre-scaled to the
* proper number of color bits:
*
* [0,ctx->Visual->RedScale]
* [0,ctx->Visual->GreenScale]
* [0,ctx->Visual->BlueScale]
* [0,ctx->Visual->AlphaScale]
*
****************************************************************************/
{
RC.color = MGL_packColorFast(&PF,r,g,b);
RC.red = r;
RC.green = g;
RC.blue = b;
}
static GLboolean index_mask(GLcontext *ctx, GLuint mask)
/****************************************************************************
*
* Function: index_mask
* Parameters: mask - Color index mask
* Returns: True if we implement masking, false if not
*
* Description: Implements color index masking ala glIndexMask if possible.
* We currently return false for this function.
*
****************************************************************************/
{
return GL_FALSE;
}
static GLboolean color_mask(GLcontext *ctx,
GLboolean rmask, GLboolean gmask,GLboolean bmask, GLboolean amask)
/****************************************************************************
*
* Function: color_mask
* Parameters: rmask - Red mask
* gmask - Green mask
* bmask - Blue mask
* amask - Alpha mask
* Returns: True if we implement masking, false if not
*
* Description: Implements RGB color masking ala glColorMask if possible.
* We currently return false for this function.
*
****************************************************************************/
{
return GL_FALSE;
}
static GLboolean logicop(GLcontext *ctx, GLenum op)
/****************************************************************************
*
* Function: logicop
* Parameters: op - New logic op to enable
* Returns: True if we implement masking, false if not
*
* Description: Implements logic operations ala glLogicOp if possible. For
* op's that we dont support we simply return GL_FALSE and it
* is implemented in software by Mesa.
*
****************************************************************************/
{
#if 0
int mode;
switch (op) {
case GL_COPY: mode = MGL_REPLACE_MODE; break;
case GL_AND: mode = MGL_AND_MODE; break;
case GL_OR: mode = MGL_OR_MODE; break;
case GL_XOR: mode = MGL_XOR_MODE; break;
default: return GL_FALSE;
}
DC.r.setWriteMode(mode);
return GL_TRUE;
#else
return GL_FALSE;
#endif
}
static void dither(GLcontext *ctx, GLboolean enable)
/****************************************************************************
*
* Function: dither
* Parameters: enable - True to enable dithering, false to disable it
*
* Description: Enables dithering mode if applicable.
*
****************************************************************************/
{
if (enable)
RC.pixelformat = RC.dithered_pf;
else
RC.pixelformat = RC.undithered_pf;
setup_DD_pointers(ctx);
}
static GLboolean set_buffer(GLcontext *ctx, GLenum mode)
/****************************************************************************
*
* Function: set_buffer
* Parameters: mode - Buffer mode to enable
*
* Description: Sets the buffer access mode to the front buffer or the
* back buffer for the application. The MGL always allows
* direct access to both buffers in double buffered fullscreen
* modes, but when rendering to a memory device context (ie:
* when rendering in a window in the windows environment) we
* only have a single buffer available.
*
****************************************************************************/
{
if (!RC.gl_vis->DBflag) {
MGL_makeCurrentDC(RC.dc);
return (mode = GL_FRONT);
}
if (RC.dc->mi.maxPage > 0) {
/* Hardware page flipping */
if (mode == GL_FRONT)
MGL_setActivePage(RC.dc,RC.frontbuffer);
else if (mode == GL_BACK)
MGL_setActivePage(RC.dc,RC.backbuffer);
else
return GL_FALSE;
}
if (RC.memdc) {
/* Software double buffering using a memory DC. In some cases
* we may not be able to access the display memory surface for the
* front buffer in which case this will fail.
*/
if (mode == GL_FRONT && (MGL_surfaceAccessType(RC.dc) != MGL_NO_ACCESS))
MGL_makeCurrentDC(RC.dc);
else if (mode == GL_BACK)
MGL_makeCurrentDC(RC.memdc);
else
return GL_FALSE;
}
else {
/* Hardware page flipping only */
MGL_makeCurrentDC(RC.dc);
}
RC.bufferMode = mode;
setup_DD_pointers(ctx);
return GL_TRUE;
}
static void get_buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
/****************************************************************************
*
* Function: get_buffer_size
* Parameters: width - Place to store buffer width
* height - Place to store buffer height
*
* Description: Returns the current buffer width and height. We simply
* return the currently active device context's width and
* height, which will change if the buffer is resized in a
* windowed environment.
*
****************************************************************************/
{
if (MI.xRes != RC.dispdc->mi.xRes || MI.yRes != RC.dispdc->mi.yRes) {
MI.xRes = RC.dispdc->mi.xRes;
MI.yRes = RC.dispdc->mi.yRes;
/* Resize our system memory back buffer if we have one */
if (RC.memdc) {
MGL_destroyDC(RC.memdc);
RC.memdc = MGL_createMemoryDC(MI.xRes+1,MI.yRes+1,MI.bitsPerPixel,&PF);
if (!RC.memdc)
exit(1);
RC.dc = RC.memdc;
if (RC.dispdc->mi.bitsPerPixel == 8) {
palette_t pal[256];
MGL_getPalette(RC.dispdc,pal,256,0);
MGL_setPalette(RC.memdc,pal,256,0);
MGL_realizePalette(RC.memdc,256,0,-1);
}
MI = RC.dc->mi;
}
}
*width = MI.xRes+1;
*height = MI.yRes+1;
RC.bottom = MI.yRes;
}
/**********************************************************************/
/*** Point rendering ***/
/**********************************************************************/
PUBLIC points_func mmesa_get_points_func(GLcontext *ctx)
/****************************************************************************
*
* Function: mmesa_get_points_func
* Parameters: ctx - Context to examine
*
* Description: Analyze context state to see if we can provide a fast points
* drawing function, like those in points.c. Otherwise, return
* NULL.
*
****************************************************************************/
{
#if 0
if (ctx->Point.Size == 1.0F && !ctx->Point.SmoothFlag && ctx->RasterMask == 0
&& !ctx->Texture.Enabled) {
return draw_points;
}
#endif
return NULL;
}
/**********************************************************************/
/*** Line rendering ***/
/**********************************************************************/
PUBLIC line_func mmesa_get_line_func(GLcontext *ctx)
/****************************************************************************
*
* Function: mmesa_get_line_func
* Parameters: ctx - Context to examine
*
* Description: Analyze context state to see if we can provide a fast line
* drawing function, like those in lines.c. Otherwise, return
* NULL.
*
****************************************************************************/
{
#if 0
XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
int depth = xmesa->xm_visual->visinfo->depth;
if (ctx->Line.SmoothFlag) return NULL;
if (ctx->Texture.Enabled) return NULL;
if (ctx->Light.ShadeModel!=GL_FLAT) return NULL;
if (xmesa->xm_buffer->buffer==XIMAGE
&& ctx->RasterMask==DEPTH_BIT
&& ctx->Depth.Func==GL_LESS
&& ctx->Depth.Mask==GL_TRUE
&& ctx->Line.Width==1.0F
&& ctx->Line.StippleFlag==GL_FALSE) {
switch (xmesa->pixelformat) {
case PF_TRUECOLOR:
return flat_TRUECOLOR_z_line;
case PF_8A8B8G8R:
return flat_8A8B8G8R_z_line;
case PF_8R8G8B:
return flat_8R8G8B_z_line;
case PF_5R6G5B:
return flat_5R6G5B_z_line;
case PF_DITHER:
return (depth==8) ? flat_DITHER8_z_line : NULL;
case PF_LOOKUP:
return (depth==8) ? flat_LOOKUP8_z_line : NULL;
case PF_HPCR:
return flat_HPCR_z_line;
default:
return NULL;
}
}
if (xmesa->xm_buffer->buffer==XIMAGE
&& ctx->RasterMask==0
&& ctx->Line.Width==1.0F
&& ctx->Line.StippleFlag==GL_FALSE) {
switch (xmesa->pixelformat) {
case PF_TRUECOLOR:
return flat_TRUECOLOR_line;
case PF_8A8B8G8R:
return flat_8A8B8G8R_line;
case PF_8R8G8B:
return flat_8R8G8B_line;
case PF_5R6G5B:
return flat_5R6G5B_line;
case PF_DITHER:
return (depth==8) ? flat_DITHER8_line : NULL;
case PF_LOOKUP:
return (depth==8) ? flat_LOOKUP8_line : NULL;
case PF_HPCR:
return flat_HPCR_line;
default:
return NULL;
}
}
if (xmesa->xm_buffer->buffer!=XIMAGE && ctx->RasterMask==0) {
setup_x_line_options( ctx );
return flat_pixmap_line;
}
#endif
return NULL;
}
/**********************************************************************/
/*** Triangle rendering ***/
/**********************************************************************/
triangle_func mmesa_get_triangle_func(GLcontext *ctx)
{
#if 0
XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
int depth = xmesa->xm_visual->visinfo->depth;
if (ctx->Polygon.SmoothFlag) return NULL;
if (ctx->Texture.Enabled) return NULL;
if (xmesa->xm_buffer->buffer==XIMAGE) {
if ( ctx->Light.ShadeModel==GL_SMOOTH
&& ctx->RasterMask==DEPTH_BIT
&& ctx->Depth.Func==GL_LESS
&& ctx->Depth.Mask==GL_TRUE
&& ctx->Polygon.StippleFlag==GL_FALSE) {
switch (xmesa->pixelformat) {
case PF_TRUECOLOR:
return smooth_TRUECOLOR_z_triangle;
case PF_8A8B8G8R:
return smooth_8A8B8G8R_z_triangle;
case PF_8R8G8B:
return smooth_8R8G8B_z_triangle;
case PF_5R6G5B:
return smooth_5R6G5B_z_triangle;
case PF_HPCR:
return smooth_HPCR_z_triangle;
case PF_DITHER:
return (depth==8) ? smooth_DITHER8_z_triangle
: smooth_DITHER_z_triangle;
case PF_LOOKUP:
return (depth==8) ? smooth_LOOKUP8_z_triangle : NULL;
default:
return NULL;
}
}
if ( ctx->Light.ShadeModel==GL_FLAT
&& ctx->RasterMask==DEPTH_BIT
&& ctx->Depth.Func==GL_LESS
&& ctx->Depth.Mask==GL_TRUE
&& ctx->Polygon.StippleFlag==GL_FALSE) {
switch (xmesa->pixelformat) {
case PF_TRUECOLOR:
return flat_TRUECOLOR_z_triangle;
case PF_8A8B8G8R:
return flat_8A8B8G8R_z_triangle;
case PF_8R8G8B:
return flat_8R8G8B_z_triangle;
case PF_5R6G5B:
return flat_5R6G5B_z_triangle;
case PF_HPCR:
return flat_HPCR_z_triangle;
case PF_DITHER:
return (depth==8) ? flat_DITHER8_z_triangle
: flat_DITHER_z_triangle;
case PF_LOOKUP:
return (depth==8) ? flat_LOOKUP8_z_triangle : NULL;
default:
return NULL;
}
}
if ( ctx->RasterMask==0 /* no depth test */
&& ctx->Light.ShadeModel==GL_SMOOTH
&& ctx->Polygon.StippleFlag==GL_FALSE) {
switch (xmesa->pixelformat) {
case PF_TRUECOLOR:
return smooth_TRUECOLOR_triangle;
case PF_8A8B8G8R:
return smooth_8A8B8G8R_triangle;
case PF_8R8G8B:
return smooth_8R8G8B_triangle;
case PF_5R6G5B:
return smooth_5R6G5B_triangle;
case PF_HPCR:
return smooth_HPCR_triangle;
case PF_DITHER:
return (depth==8) ? smooth_DITHER8_triangle
: smooth_DITHER_triangle;
case PF_LOOKUP:
return (depth==8) ? smooth_LOOKUP8_triangle : NULL;
default:
return NULL;
}
}
if ( ctx->RasterMask==0 /* no depth test */
&& ctx->Light.ShadeModel==GL_FLAT
&& ctx->Polygon.StippleFlag==GL_FALSE) {
switch (xmesa->pixelformat) {
case PF_TRUECOLOR:
return flat_TRUECOLOR_triangle;
case PF_8A8B8G8R:
return flat_8A8B8G8R_triangle;
case PF_8R8G8B:
return flat_8R8G8B_triangle;
case PF_5R6G5B:
return flat_5R6G5B_triangle;
case PF_HPCR:
return flat_HPCR_triangle;
case PF_DITHER:
return (depth==8) ? flat_DITHER8_triangle
: flat_DITHER_triangle;
case PF_LOOKUP:
return (depth==8) ? flat_LOOKUP8_triangle : NULL;
default:
return NULL;
}
}
return NULL;
}
else {
/* pixmap */
if (ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0) {
setup_x_polygon_options( ctx );
return flat_pixmap_triangle;
}
return NULL;
}
#endif
return NULL;
}
/**********************************************************************/
/*** Quad rendering ***/
/**********************************************************************/
quad_func mmesa_get_quad_func(GLcontext *ctx)
{
return NULL;
}
/**********************************************************************/
/*** 2D Rectangle Rendering ***/
/**********************************************************************/
rect_func mmesa_get_rect_func(GLcontext *ctx)
{
return NULL;
}
/**********************************************************************/
/***** Miscellaneous functions *****/
/**********************************************************************/
static const char *renderer_string(void)
{
return "SciTech MGL " MGL_VERSION_STR;
}
static void setup_DD_pointers(GLcontext *ctx)
/****************************************************************************
*
* Function: setup_DD_pointer
* Parameters: ctx - Device context to setup pointers for
*
* Description: Sets up all the device driver rendering pointers for the
* current rendering state. This function is where we swap in
* high performance rendering functions when the rendering
* state allows this.
*
****************************************************************************/
{
ibool doDither = false;
/* Mandatory functions that are always the same */
ctx->Driver.RendererString = renderer_string;
ctx->Driver.UpdateState = setup_DD_pointers;
ctx->Driver.ClearIndex = clear_index;
ctx->Driver.ClearColor = clear_color;
ctx->Driver.Clear = clear;
ctx->Driver.Index = set_index;
ctx->Driver.Color = set_color;
ctx->Driver.SetBuffer = set_buffer;
ctx->Driver.GetBufferSize = get_buffer_size;
/* Driver functions that are always the same */
ctx->Driver.Begin = begin;
ctx->Driver.End = end;
ctx->Driver.Flush = flush;
ctx->Driver.Finish = finish;
ctx->Driver.IndexMask = index_mask;
ctx->Driver.ColorMask = color_mask;
ctx->Driver.LogicOp = logicop;
ctx->Driver.Dither = dither;
/* Accelerated point, line and triangle functions */
ctx->Driver.PointsFunc = mmesa_get_points_func(ctx);
ctx->Driver.LineFunc = mmesa_get_line_func(ctx);
ctx->Driver.TriangleFunc = mmesa_get_triangle_func(ctx);
ctx->Driver.QuadFunc = mmesa_get_quad_func(ctx);
ctx->Driver.RectFunc = mmesa_get_rect_func(ctx);
/* Accelerated bitmap drawing functions */
#if 0
ctx->Driver.DrawPixels = draw_pixels;
ctx->Driver.Bitmap = draw_bitmap;
#endif
/* Optimized pixel span reading/writing functions. Note that we use
* a (void*) cast as we have removed the 'const'ness of the parameters
* passed to these functions so we can use the pointers to step through
* our arrays efficiently.
*/
switch (RC.pixelformat) {
case PF_INDEX:
ctx->Driver.WriteCI32Span = (void*)(void*)_mmesa_write_span_ci;
ctx->Driver.WriteCI8Span = (void*)_mmesa_write_span_ci8;
ctx->Driver.WriteMonoCISpan = (void*)_mmesa_write_span_mono_ci;
ctx->Driver.WriteCI32Pixels = (void*)_mmesa_write_pixels_ci;
ctx->Driver.WriteMonoCIPixels = (void*)_mmesa_write_pixels_mono_ci;
ctx->Driver.ReadCI32Span = (void*)_mmesa_read_span_ci;
ctx->Driver.ReadCI32Pixels = (void*)_mmesa_read_pixels_ci;
break;
case PF_RGB8:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_8_8;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_8_8;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_8;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_8_8;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_8;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_8_8;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_8_8;
doDither = true;
break;
case PF_DITHER8:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_8_DITHER8;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_8_DITHER8;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_8_DITHER8;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_8_DITHER8;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_8_DITHER8;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_8_8;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_8_8;
doDither = true;
break;
case PF_RGB555:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_16_555;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_16_555;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_16;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_16_555;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_16;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_16_555;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_16_555;
break;
case PF_DITHER555:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_16_DITHER555;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_16_DITHER555;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_16_DITHER555;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_16_DITHER555;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_16_DITHER555;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_16_555;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_16_555;
doDither = true;
break;
case PF_RGB565:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_16_565;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_16_565;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_16;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_16_565;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_16;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_16_565;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_16_565;
break;
case PF_DITHER565:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_16_DITHER565;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_16_DITHER565;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_16_DITHER565;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_16_DITHER565;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_16_DITHER565;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_16_565;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_16_565;
doDither = true;
break;
case PF_RGB888:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_24_RGB;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_24_RGB;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_24_RGB;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_24_RGB;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_24_RGB;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_24_RGB;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_24_RGB;
break;
case PF_BGR888:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_24_BGR;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_24_BGR;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_24_BGR;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_24_BGR;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_24_BGR;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_24_BGR;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_24_BGR;
break;
case PF_ARGB8888:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_32_ARGB;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_32_ARGB;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_32;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_32_ARGB;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_32;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_32_ARGB;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_32_ARGB;
break;
case PF_ABGR8888:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_32_ABGR;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_32_ABGR;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_32;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_32_ABGR;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_32;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_32_ABGR;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_32_ABGR;
break;
case PF_RGBA8888:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_32_RGBA;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_32_RGBA;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_32;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_32_RGBA;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_32;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_32_RGBA;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_32_RGBA;
break;
case PF_BGRA8888:
ctx->Driver.WriteRGBASpan = (void*)_mmesa_write_span_32_BGRA;
ctx->Driver.WriteRGBSpan = (void*)_mmesa_write_span_rgb_32_BGRA;
ctx->Driver.WriteMonoRGBASpan = (void*)_mmesa_write_span_mono_32;
ctx->Driver.WriteRGBAPixels = (void*)_mmesa_write_pixels_32_BGRA;
ctx->Driver.WriteMonoRGBAPixels = (void*)_mmesa_write_pixels_mono_32;
ctx->Driver.ReadRGBASpan = (void*)_mmesa_read_span_32_BGRA;
ctx->Driver.ReadRGBAPixels = (void*)_mmesa_read_pixels_32_BGRA;
break;
}
}
/**********************************************************************/
/***** MGLMesa API Functions *****/
/**********************************************************************/
#ifdef __WINDOWS__
ibool APIENTRY MGLMesaInitDLL(MGLCallbacks *cb,char *version)
/****************************************************************************
*
* Function: MGLMesaInitDLL
* Parameters: cb - MGL callbacks structure
* version - MGL version this DLL was built for
*
* Description: This function is called by the MGL when the MESAGL.DLL
* library is loaded under Windows. This registers a set of
* callback functions that Mesa uses to call MGL API functions
* so that we dont have to staticly link the MGL and Mesa into
* the same DLL or application.
*
* We also pass back a copy of Mesa's internal global MGL
* device context which Mesa uses to directly access the MGL
* internal functions and structures. The MGL uses this pointer
* to maintain Mesa's internal structures
*
* Note that because we use the MGL's internal structures we
* also do a check to ensure that the MGL library calling us
* is the same version that we were built with.
*
****************************************************************************/
{
/* Check for the correct MGL version */
if (strcmp(version,MGL_VERSION_STR) != 0)
return false;
_MGL_callbacks = *cb;
return true;
}
#endif
void APIENTRY MGLMesaChooseVisual(MGLDC *dc,MGLVisual *visual)
/****************************************************************************
*
* Function: MGLMesaChooseVisual
* Parameters: dc - MGL device context
* visual - Structure containing visual context information
*
* Description: This function examines the visual passed to use to
* deteremine if we support the requested capabilities. If we
* don't we will modify the structure for the capabilities that
* we do support (ie: lowering the depth buffer size to 16
* bits etc).
*
****************************************************************************/
{
/* Force the depth buffer, stencil buffer and accum buffers to our sizes */
if (visual->depth_size)
visual->depth_size = 8 * sizeof(GLdepth);
if (visual->stencil_size)
visual->stencil_size = 8 * sizeof(GLstencil);
if (visual->accum_size)
visual->accum_size = 8 * sizeof(GLaccum);
/* Force RGB mode for DirectColor and TrueColor modes */
if (dc->mi.bitsPerPixel > 8)
visual->rgb_flag = GL_TRUE;
if (MGL_isMemoryDC(dc))
visual->db_flag = GL_FALSE;
if (MGL_isWindowedDC(dc) || MGL_surfaceAccessType(dc) == MGL_NO_ACCESS)
visual->db_flag = GL_TRUE;
}
static int countBits(uint mask)
/****************************************************************************
*
* Function: countBits
* Parameters: mask -
* Returns: number of set bits.
*
* Description: Counts the number of set bits in a mask and determines the
* shift amount.
*
****************************************************************************/
{
int i=0;
if (mask) {
/* count set bits */
while ( mask & (1 << i)) {
i++;
};
}
return i;
}
ibool APIENTRY MGLMesaSetVisual(MGLDC *dc,MGLVisual *vis)
/****************************************************************************
*
* Function: MGLMesaSetVisual
* Parameters: dc - MGL device context
* visual - Structure containing visual context information
* Returns: True on success, false if visual creation failed
*
* Description: This function attempts to create a Mesa visual for the
* device context. If this succeeds then Mesa can properly
* handle the requested visual.
*
****************************************************************************/
{
GLfloat red_scale, green_scale, blue_scale, alpha_scale;
GLint red_bits, green_bits, blue_bits, alpha_bits;
/* Do quick check on incoming visual */
if (dc->mi.bitsPerPixel > 8 && !vis->rgb_flag)
return false;
if (dc->mi.bitsPerPixel < 8)
return false;
if ((dc->mi.xRes+1 > MAX_WIDTH) || (dc->mi.yRes+1 > MAX_HEIGHT))
return false;
if (MGL_isMemoryDC(dc) && vis->db_flag)
return false;
if ((MGL_isWindowedDC(dc) || MGL_surfaceAccessType(dc) == MGL_NO_ACCESS) && !vis->db_flag)
return false;
/* Create color channel scale factors from pixel format info */
red_scale = (GLfloat)dc->pf.redMask;
green_scale = (GLfloat)dc->pf.greenMask;
blue_scale = (GLfloat)dc->pf.blueMask;
alpha_scale = 255.0;
red_bits = countBits(dc->pf.redMask);
green_bits = countBits(dc->pf.greenMask);
blue_bits = countBits(dc->pf.blueMask);
alpha_bits = countBits(dc->pf.rsvdMask);
MGL_clearCurrentDC();
dc->visual = gl_create_visual( vis->rgb_flag,
vis->alpha_flag,
vis->db_flag,
GL_FALSE, /* stereo */
vis->depth_size,
vis->stencil_size,
vis->accum_size,
dc->mi.bitsPerPixel,
red_bits,
green_bits,
blue_bits,
alpha_bits);
return (dc->visual != NULL);
}
ibool APIENTRY MGLMesaCreateContext(MGLDC *dc,ibool forceMemDC)
/****************************************************************************
*
* Function: MGLMesaCreateContext
* Parameters: dc - MGLDC to create rendering context for
* forceMemDC - True to force rendering to memory back buffer
* Returns: True on success, false on failure.
*
* Description: Attempts to create a Mesa rendering context for the
* device context. The application programmer must first
* call MGLMesaSetVisual on the MGLDC to set the visual format
* before calling this function.
*
* If we dont have hardware page flipping or the user has
* forced memory buffering with the forceMemDC function then
* we will allocate a system memory back buffer for double
* buffering. Note that if we have hardware page flipping
* and system buffering has been forced, we will still flip
* between hardware pages to eliminate all tearing. This
* option is intended mainly as a performance option for
* systems where system memory rendering is faster.
*
****************************************************************************/
{
palette_t pal[256];
/* Ensure that the visual has been created first */
MGL_clearCurrentDC();
if (!dc->visual)
return false;
/* Allocate memory for the rendering context structure and create it */
if ((dc->rc = (void*)calloc(1,sizeof(MGLRC))) == NULL)
goto Error;
dc->rc->dispdc = dc;
dc->rc->gl_ctx = gl_create_context(dc->visual,NULL,(void*)dc->rc, GL_TRUE);
if (!dc->rc)
goto Error;
/* Allocate the ancillary buffers */
if ((dc->rc->gl_buffer = gl_create_framebuffer(dc->visual)) == NULL)
goto Error;
/* Allocate back memory DC buffer if necessary */
if ((dc->visual->DBflag && dc->mi.maxPage == 0) || forceMemDC || (MGL_surfaceAccessType(dc) == MGL_NO_ACCESS)) {
dc->rc->memdc = MGL_createMemoryDC(dc->mi.xRes+1,dc->mi.yRes+1,dc->mi.bitsPerPixel,&dc->pf);
if (!dc->rc->memdc)
goto Error;
dc->rc->dc = dc->rc->memdc;
}
else
dc->rc->dc = dc->rc->dispdc;
/* Initialize double buffering */
if (dc->visual->DBflag && dc->mi.maxPage > 0) {
MGL_setVisualPage(dc,dc->rc->frontbuffer = 0,false);
MGL_setActivePage(dc,dc->rc->backbuffer = 1);
}
/* Initialize the private rendering context information */
if (!dc->visual->RGBAflag) {
dc->rc->dithered_pf = dc->rc->undithered_pf = PF_INDEX;
MGL_getPalette(dc,pal,256,0);
}
else {
if (dc->mi.bitsPerPixel > 8) {
/* DirectColor or TrueColor display */
if (dc->mi.bitsPerPixel == 15) {
dc->rc->undithered_pf = PF_RGB555;
dc->rc->dithered_pf = PF_DITHER555;
}
else if (dc->mi.bitsPerPixel == 16) {
dc->rc->undithered_pf = PF_RGB565;
dc->rc->dithered_pf = PF_DITHER565;
}
else if (dc->mi.bitsPerPixel == 24) {
if (dc->pf.redPos == 0)
dc->rc->undithered_pf = dc->rc->dithered_pf = PF_BGR888;
else
dc->rc->undithered_pf = dc->rc->dithered_pf = PF_RGB888;
}
else {
if (dc->pf.redPos == 0)
dc->rc->undithered_pf = dc->rc->dithered_pf = PF_ABGR8888;
else if (dc->pf.redPos == 8)
dc->rc->undithered_pf = dc->rc->dithered_pf = PF_BGRA8888;
else if (dc->pf.redPos == 16)
dc->rc->undithered_pf = dc->rc->dithered_pf = PF_ARGB8888;
else
dc->rc->undithered_pf = dc->rc->dithered_pf = PF_RGBA8888;
}
}
else {
/* 8bpp RGB display */
dc->rc->undithered_pf = PF_RGB8;
dc->rc->dithered_pf = PF_DITHER8;
MGL_getHalfTonePalette(pal);
}
}
dc->rc->gl_vis = dc->visual;
dc->rc->bottom = dc->mi.yRes+1;
dc->rc->pixelformat = dc->rc->dithered_pf;
dc->rc->bufferMode = dc->visual->DBflag ? GL_BACK : GL_FRONT;
setup_DD_pointers(dc->rc->gl_ctx);
/* Setup the default palette for the device context */
if (dc->mi.bitsPerPixel == 8) {
MGLMesaSetPalette(dc,pal,256,0);
MGLMesaRealizePalette(dc,256,0,false);
}
return true;
Error:
MGLMesaDestroyContext(dc);
return false;
}
void APIENTRY MGLMesaDestroyContext(MGLDC *dc)
/****************************************************************************
*
* Function: MGLMesaDestroyContext
* Parameters: dc - MGLDC to destroy rendering context for
*
* Description: Destroys the rendering context and returns the MGLDC back
* to it's original state before 3D rendering was enabled.
*
****************************************************************************/
{
if (dc->rc) {
if (dc->rc->memdc)
MGL_destroyDC(dc->rc->memdc);
gl_destroy_framebuffer(dc->rc->gl_buffer);
gl_destroy_context(dc->rc->gl_ctx);
free(dc->rc);
}
dc->rc = NULL;
gl_destroy_visual(dc->visual);
dc->visual = NULL;
}
void APIENTRY MGLMesaMakeCurrent(MGLDC *dc)
/****************************************************************************
*
* Function: MGLMesaMakeCurrent
* Parameters: dc - MGLDC to make current
*
* Description: Makes the passed in MGLDC the current rendering context
* for OpenGL functions. Note that we cache a global copy
* of this rendering context for speed (we are single threaded)
* so we flush this back when the context is made a different
* one.
*
****************************************************************************/
{
if (dc && dc->rc == _MM_rcPtr)
return;
if (_MM_rcPtr) {
*_MM_rcPtr = RC; /* 'Write back' the old RC */
_MM_rcPtr = NULL; /* This RC is no longer cached */
gl_make_current(NULL, NULL);
MGL_clearCurrentDC();
}
if (dc) {
gl_make_current(dc->rc->gl_ctx, dc->rc->gl_buffer);
_MM_rcPtr = dc->rc; /* Cache DC in global structure */
RC = *dc->rc; /* Save pointer to original DC */
MI = RC.dc->mi; /* Save cached MGL internals */
PF = RC.dc->pf;
VECS = RC.dc->r;
set_buffer(dc->rc->gl_ctx,RC.bufferMode);
if (RC.gl_ctx->Viewport.Width == 0) {
/* initialize viewport to window size */
gl_Viewport(RC.gl_ctx, 0, 0, MI.xRes+1, MI.yRes+1);
RC.gl_ctx->Scissor.Width = MI.xRes+1;
RC.gl_ctx->Scissor.Height = MI.yRes+1;
}
}
}
void APIENTRY MGLMesaSwapBuffers(MGLDC *dc,ibool waitVRT)
/****************************************************************************
*
* Function: MGLMesaSwapBuffers
* Parameters: dc - MGLDC to swap buffers for
* waitVRT - True to wait for vertical retrace
*
* Description: Swaps the display buffers for the MGL device context. If
* we have a memory DC this is blitted to the display, and
* if we have harware page flipping we flip hardware display
* pages.
*
****************************************************************************/
{
if (!RC.gl_vis->DBflag)
return;
if (RC.memdc) {
/* We have a memory buffer so blit it to the screen */
MGL_bitBltCoord(RC.dispdc,RC.memdc,0,0,MI.xRes+1,MI.yRes+1,0,0,MGL_REPLACE_MODE);
}
if (RC.dc->mi.maxPage > 0) {
/* Hardware page flipping */
RC.frontbuffer ^= 1;
RC.backbuffer = RC.frontbuffer ^ 1;
if (RC.bufferMode == GL_FRONT)
MGL_setActivePage(RC.dc,RC.frontbuffer);
else
MGL_setActivePage(RC.dc,RC.backbuffer);
MGL_setVisualPage(RC.dc,RC.frontbuffer,waitVRT);
}
}
void APIENTRY MGLMesaSetPaletteEntry(MGLDC *dc,int entry,uchar red,uchar green,uchar blue)
/****************************************************************************
*
* Function: MGLMesaSetPaletteEntry
* Parameters: dc - MGLDC to destroy rendering context for
* entry - Index of entry to set
* red,... - Color values for palette entry
*
* Description: Sets a single color palette entry in the device context.
*
****************************************************************************/
{
MGL_setPaletteEntry(dc,entry,red,green,blue);
if (dc->rc && dc->rc->memdc)
MGL_setPaletteEntry(dc->rc->memdc,entry,red,green,blue);
}
void APIENTRY MGLMesaSetPalette(MGLDC *dc,palette_t *pal,int numColors,int startIndex)
/****************************************************************************
*
* Function: MGLMesaDestroyContext
* Parameters: dc - MGLDC to destroy rendering context for
*
* Description: Destroys the rendering context and returns the MGLDC back
* to it's original state before 3D rendering was enabled.
*
****************************************************************************/
{
MGL_setPalette(dc,pal,numColors,startIndex);
if (dc->rc && dc->rc->memdc)
MGL_setPalette(dc->rc->memdc,pal,numColors,startIndex);
}
void APIENTRY MGLMesaRealizePalette(MGLDC *dc,int numColors,int startIndex,int waitVRT)
/****************************************************************************
*
* Function: MGLMesaDestroyContext
* Parameters: dc - MGLDC to destroy rendering context for
*
* Description: Destroys the rendering context and returns the MGLDC back
* to it's original state before 3D rendering was enabled.
*
****************************************************************************/
{
MGL_realizePalette(dc,numColors,startIndex,waitVRT);
if (dc->rc && dc->rc->memdc)
MGL_realizePalette(dc->rc->memdc,numColors,startIndex,waitVRT);
}